package com.tangosol.coherence.component.util.daemon.queueProcessor.service.grid;

import com.oracle.coherence.patterns.security.extend.ExtendAccessController;
import com.oracle.coherence.patterns.security.proxy.SecureCacheServiceProxy;
import com.oracle.coherence.patterns.security.proxy.SecureInvocationServiceProxy;
import com.tangosol.coherence.Component;
import com.tangosol.coherence.component.net.extend.proxy.CacheServiceProxy;
import com.tangosol.coherence.component.net.extend.proxy.InvocationServiceProxy;
import com.tangosol.run.xml.XmlElement;
import com.tangosol.run.xml.XmlHelper;

/**
 * This class is an extension to the Coherence ProxyService.
 * <p/>
 * This class overrides the <code>setCacheServiceProxy</code>
 * and <code>setInvocationServiceProxy</code> methods to use secure proxy services.
 * This class also allows the {@link com.oracle.coherence.patterns.security.extend.ExtendAccessController} class
 * to be set in the Coherence operational configuration file.
 * <p/>
 * <b>Note</b> This class relies on overriding the undocumented internals of the Coherence ProxyService class.
 * This class has so far been tested to work against version 3.4 - 3.5.2 of Coherence only.
 * <p/>
 *
 * @author Jonathan Knight
 */
public class SecureProxyService extends ProxyService {
    /**
     * flag to indicate if security is enabled
     */
    private boolean isSecured;

    /**
     * The AccessController that will be used by the proxied services
     */
    private ExtendAccessController accessController;

    /**
     * Empty public constructor.<p/>
     */
    public SecureProxyService() {
    }

    /**
     * Constructor from super class.<p/>
     *
     * @param s         -
     * @param component -
     * @param b         -
     */
    public SecureProxyService(String s, Component component, boolean b) {
        super(s, component, b);
    }

    /**
     * Configure this ProxyService.<p/>
     * This method overrides the {@link ProxyService#configure(XmlElement)} method and allows
     * settings for enabling security and configuring the {@link ExtendAccessController} that
     * will be used.
     * <p/>
     * @param xmlConfig - the XML to use to configure this ProxyService
     */
    @Override
    public void configure(XmlElement xmlConfig) {
        XmlElement xmlSecurity = xmlConfig.getSafeElement("security-config");
        isSecured = xmlSecurity.getSafeElement("enabled").getBoolean(false);
        if (isSecured) {
            XmlElement xmlAccessController = xmlSecurity.getElement("access-controller");
            if (xmlAccessController != null) {
                accessController = (ExtendAccessController) XmlHelper.createInstance(xmlAccessController, null, null);
            }
        }
        super.configure(xmlConfig);
    }

    /**
     * This method is overrides the parent implementation.<p>
     * Regardless of what CacheServiceProxy instance is passed in
     * the CacheServiceProxy is set to a new instance of SecureCacheServiceProxy.
     *
     * @param cacheServiceProxy - ignored
     */
    @Override
    protected void setCacheServiceProxy(CacheServiceProxy cacheServiceProxy) {
        if (isSecured && accessController != null) {
            super.setCacheServiceProxy(new SecureCacheServiceProxy(accessController));
        } else {
            super.setCacheServiceProxy(cacheServiceProxy);
        }
    }

    /**
     * This method is overrides the parent implementation.<p>
     * Regardless of what InvocationServiceProxy instance is passed in
     * the InvocationServiceProxy is set to a new instance of SecureInvocationServiceProxy.
     *
     * @param invocationServiceProxy - ignored
     */
    @Override
    protected void setInvocationServiceProxy(InvocationServiceProxy invocationServiceProxy) {
        if (isSecured && accessController != null) {
            super.setInvocationServiceProxy(new SecureInvocationServiceProxy(accessController));
        } else {
            super.setInvocationServiceProxy(invocationServiceProxy);
        }
    }

    /**
     * All Coherence Compaonent classes implement this method.<p/>
     *
     * @return the class of this class.
     */
    public static Class get_CLASS() {
        return SecureProxyService.class;
    }

    /**
     * All Coherence Compaonent classes implement this method.<p/>
     *
     * @return a new instance of SecureProxyService.
     */
    public static Component get_Instance() {
        return new SecureProxyService();
    }

}